// (C) Copyright 2012 Kystar. All rights reserved.

`timescale 1ns/100ps

module yuv2rgb 
(
    input  I_pclk,
    input  I_vsync,
    input  I_hsync,
    input  I_de,
    input  [ 23: 0] I_data,
    output O_vsync,
    output O_hsync,
    output O_de,
    output [ 23: 0] O_data,
    input  I_enable
);

/******************************************************************************
                                <localparams>
******************************************************************************/

/******************************************************************************
                              <internal signals>
******************************************************************************/
reg  vsync_0, hsync_0, de_0;
reg  vsync_1, hsync_1, de_1;
reg  vsync_2, hsync_2, de_2;
reg  vsync_3, hsync_3, de_3;
reg  vsync_4, hsync_4, de_4;
reg  vsync_5, hsync_5, de_5;
reg  [ 23: 0] data_1, data_2, data_3, data_4, data_5;
reg  [ 7: 0] Y, U, V;
reg  signed [ 8: 0] signed_y, signed_u, signed_v;
reg  signed [ 18: 0] signed_r_1, signed_r_2, signed_r_3;
reg  signed [ 9: 0] signed_g_1, signed_g_2, signed_g_3;
reg  signed [ 18: 0] signed_b_1, signed_b_2, signed_b_3;
reg  signed [ 19: 0] signed_r_12;
reg  signed [ 10: 0] signed_g_12;
reg  signed [ 19: 0] signed_b_12;
reg  signed [ 19: 0] signed_r_3_dly;
reg  signed [ 9: 0] signed_g_3_dly;
reg  signed [ 19: 0] signed_b_3_dly;
reg  signed [ 19: 0] signed_r;
reg  signed [ 10: 0] signed_g;
reg  signed [ 19: 0] signed_b;
reg  [ 7: 0] r, g, b;

/******************************************************************************
                                <module body>
******************************************************************************/
always @(posedge I_pclk)
    begin
    vsync_0 <= I_vsync;
    hsync_0 <= I_hsync;
    de_0 <= I_de;
    Y <= I_data[23:16];
    U <= I_data[15:8];
    V <= I_data[7:0];
    end

always @(posedge I_pclk)
    begin
    vsync_1 <= vsync_0;
    hsync_1 <= hsync_0;
    de_1 <= de_0;
    data_1 <= {Y,U,V};
    signed_y <= {1'b0, Y};
    signed_u <= U - 128;
    signed_v <= V - 128;
    end

always @(posedge I_pclk)
    begin
    vsync_2 <= vsync_1;
    hsync_2 <= hsync_1;
    de_2 <= de_1;
    data_2 <= data_1;
    signed_r_1 <= {signed_y,9'd0};
    signed_r_2 <= signed_u * 171;
    signed_r_3 <= signed_v * 853;
    end

always @(posedge I_pclk)
    begin
    signed_g_1 <= signed_y;
    signed_g_2 <= 0 - signed_u;
    signed_g_3 <= 0 - signed_v;
    end

always @(posedge I_pclk)
    begin
    signed_b_1 <= {signed_y,9'd0};
    signed_b_2 <= signed_u * 853;
    signed_b_3 <= signed_v * 171;
    end

always @(posedge I_pclk)
    begin
    vsync_3 <= vsync_2;
    hsync_3 <= hsync_2;
    de_3 <= de_2;
    data_3 <= data_2;
    signed_r_12 <= signed_r_1 + signed_r_2;
    signed_g_12 <= signed_g_1 + signed_g_2;
    signed_b_12 <= signed_b_1 + signed_b_2;
    signed_r_3_dly <= signed_r_3;
    signed_g_3_dly <= signed_g_3;
    signed_b_3_dly <= signed_b_3;
    end

always @(posedge I_pclk)
    begin
    vsync_4 <= vsync_3;
    hsync_4 <= hsync_3;
    de_4 <= de_3;
    data_4 <= data_3;
    signed_r <= signed_r_12 + signed_r_3_dly;
    signed_g <= signed_g_12 + signed_g_3_dly;
    signed_b <= signed_b_12 + signed_b_3_dly;
    end

always @(posedge I_pclk)
    begin
    vsync_5 <= vsync_4;
    hsync_5 <= hsync_4;
    de_5 <= de_4;
    data_5 <= data_4;
    r <= signed_r[19] ? 0 : signed_r[18:17] != 0 ? 255 : signed_r[16:9];
    g <= signed_g[10] ? 0 : signed_g[9:8] != 0 ? 255 : signed_g[7:0];
    b <= signed_b[19] ? 0 : signed_b[18:17] != 0 ? 255 : signed_b[16:9];
    end

assign O_data = I_enable ? {r,g,b} : data_5;
assign O_vsync = vsync_5;
assign O_hsync = hsync_5;
assign O_de = de_5;

endmodule

